<?php

namespace App\Http\Controllers\Backstage\System;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Validation\Rule;
use App\Services\RoleService;
use App\Services\UserService;
use App\Services\MenuPermissionService;
use App\Role;
use App\MenuPermission;
use App\Lib\Auth\UserProfileHelper;

class RoleController extends Controller
{
    private $roleService = null;
    private $userService = null;
    private $userProfileHelper = null;
    private $menuPermissionService = null;

    public function __construct(RoleService $roleService,
        UserService $userService,
        MenuPermissionService $menuPermissionService,
        UserProfileHelper $userProfileHelper)
    {
        $this->userService = $userService;
        $this->roleService = $roleService;
        $this->menuPermissionService = $menuPermissionService;
        $this->userProfileHelper = $userProfileHelper;
    }

    public function index()
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            return view('backstage.system.role.role');
        } else {
            return view('backstage.system.user.no_org');
        }
    }

    public function query(Request $request)
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

            $input = $request->all();
            $input['groupId'] = $currentUserGroupId;

            return $this->roleService->getRoles($input);
        }

        return [];
    }

    public function create()
    {
        return view('backstage.system.role.create');
    }

    public function saveNew(Request $request)
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

            $input = $request->all();
            $input['group_id'] = $currentUserGroupId;

            $this->validateWhenSaveNew($input);

            Role::create($input);

            return response()->json([
                'Success' => true,
                'Message' => '新增角色成功',
            ]);
        }

        return response()->json([
            'Success' => false,
            'Message' => '角色创建失败，找不到当前用户组',
        ]);
    }

    public function edit($roleId)
    {
        $role = Role::findOrFail($roleId);
        return view('backstage.system.role.create', [
            'role' => $role
        ]);
    }

    public function update(Request $request)
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

            $input = $request->all();
            $input['group_id'] = $currentUserGroupId;

            $this->validateWhenSaveUpdate($input);

            $role = Role::findOrFail($input['id']);
            if ($this->roleService->isRoleAsDefaultGroupRole($input['id'])) {
                //如果是当前用户组下的默认角色，则不可改名，只能改其它内容
                $input['name'] = $role->name;
            }
            $role->update($input);

            return response()->json([
                'Success' => true,
                'Message' => '保存修改角色成功',
            ]);
        }

        return response()->json([
            'Success' => false,
            'Message' => '角色修改失败，找不到当前用户组',
        ]);
    }

    public function delete(Request $request)
    {
        $input = $request->all();

        $this->validateWhenDelete($input);

        $this->roleService->deleteRole($input['id']);

        return response()->json([
            'Success' => true,
            'Message' => '删除角色成功',
        ]);
    }

    public function getPermissionsByRole($roleId)
    {
        if ($this->isTheRoleInCurrentGroup($roleId)) {
            $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];
            $group = $this->userProfileHelper->getCurrentUserGroup($currentUserGroupId);

            if ($group->isExternalEnterprise()) {
                $menuPermissions = $this->roleService->getGroupMenuPermission($group->partner_group_type_id, 4);
                $perms = $this->roleService->getRolePermissions($roleId);
            } else {
                $menuPermissions = $this->menuPermissionService->getCascadeMenuPermissionByLevel(4);
                $perms = $this->roleService->getRolePermissions($roleId);
            }

            return view('backstage.system.role.permission', [
                'roleId' => $roleId,
                'menuPermissions' => $menuPermissions,
                'currentPermssionIds' => $perms
            ]);
        }

        return response()->json([
            'Success' => false,
            'Message' => '您尚未授权访问此角色',
        ]);

    }

    public function saveRolePermissions(Request $request)
    {
        $input = $request->all();

        $this->validateWhenSavePermission($input);

        $permissionIds = explode(',', $input['perms']);

        $this->roleService->saveRolePermissions($input['roleId'], $permissionIds);

        return response()->json([
            'Success' => true,
            'Message' => '保存权限成功',
        ]);
    }

    private function validateWhenSavePermission(Array $input)
    {
        return Validator::make($input, [
                'roleId' => [
                    'required',
                    Rule::in(collect($this->getCurrentRoles())->pluck('id')->toArray())
                ],
            ], [
                'roleId.required' => '必须传入角色ID',
                'roleId.in' => '输入的角色id不属于当前组织',
            ])->after(function ($validator) use($input) {
                if ($input['perms'] !== '') {
                    $permissionIds = explode(',', $input['perms']);
                    $allPermissions = collect($this->menuPermissionService->getMenuPermissions([], [
                        MenuPermission::$PERMISSION_TYPE_TOP_NAVI,
                        MenuPermission::$PERMISSION_TYPE_MENU_GROUP,
                        MenuPermission::$PERMISSION_TYPE_MENU,
                        MenuPermission::$PERMISSION_TYPE_OPERATION
                    ], false))->pluck('id')->toArray();

                    $defaultPermission = $this->menuPermissionService->getDefaultMenuPermission();

                    if (empty($defaultPermission)) {
                        $validator->errors()->add('perms.no_default', '系统尚未设置默认菜单，不可继续');
                    } else {
                        $illegalPermission = true;
                        $hasSetDefault = false;
                        foreach ($permissionIds as $permissionId) {
                            if (!empty($permissionId)) {
                                $illegalPermission = $illegalPermission && in_array($permissionId, $allPermissions);
                                $hasSetDefault = $hasSetDefault || ($permissionId == $defaultPermission->id);
                            }
                        }

                        if (!$illegalPermission) {
                            $validator->errors()->add('perms.illegal', '传入的权限ID里有不合法的数据');
                        }

                        if (!$hasSetDefault) {
                            $validator->errors()->add('perms.has_default', '没有设置默认菜单，会导致无法正常访问');
                        }
                    }

                } else {
                    $validator->errors()->add('perms.required', '至少要选择一个权限');
                }
            }
        )->validate();
    }

    private function isTheRoleInCurrentGroup($roleId)
    {
        return in_array($roleId, collect($this->getCurrentRoles())->pluck('id')->toArray());
    }

    private function validateWhenSaveNew(Array $input)
    {
        return Validator::make($input, [
            'name' => [
                'required',
                'max:50',
                Rule::unique('roles')->where(function ($query) use($input) {
                    $query->where('name', $input['name'])
                        ->where('group_id', $input['group_id']);
                })
            ],
            'description' => 'max:100'
        ], [
            'name.required' => '角色名称必须存在',
            'name.max' => '角色名称长度不可超过:max',
            'name.unique' => '角色名称不可重复',
            'description.max' => '角色描述长度不可超过:max',
        ])->validate();
    }

    private function getCurrentRoles()
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

            return $this->roleService->getRoles(['groupId'=>$currentUserGroupId], false);
        }

        return [];
    }
    private function validateWhenSaveUpdate(Array $input)
    {
        return Validator::make($input, [
            'id' => [
                'required',
                Rule::in(collect($this->getCurrentRoles())->pluck('id')->toArray())
            ],
            'name' => [
                'required',
                'max:50',
                Rule::unique('roles')->where(function ($query) use($input) {
                    $query->where('name', $input['name'])
                        ->where('group_id', $input['group_id'])
                        ->where('id', '<>', $input['id']);
                })
            ],
            'description' => 'max:100'
        ], [
            'id.required' => '角色id必须存在',
            'id.in' => '输入的角色id不属于当前组织',
            'name.required' => '角色名称必须存在',
            'name.max' => '角色名称长度不可超过:max',
            'name.unique' => '角色名称不可重复',
            'description.max' => '角色描述长度不可超过:max',
        ])->validate();
    }

    private function validateWhenDelete(Array $input)
    {
        return Validator::make($input, [
                'id' => [
                    'required',
                    Rule::in(collect($this->getCurrentRoles())->pluck('id')->toArray())
                ],
            ], [
                'id.required' => '角色id必须存在',
                'id.in' => '输入的角色id不属于当前组织',
            ])->after(function ($validator) use($input) {
                if ($this->roleService->isTheOnlyOneExistsRole($input['id'])) {
                    $validator->errors()->add('id.roleIsOnlyOne', '该角色已经是当前组织下最后一个角色了，不可删除');
                }
                if ($this->roleService->isRoleAsDefaultGroupRole($input['id'])) {
                    $validator->errors()->add('id.roleIsDefault', '该角色是该组织下的默认角色，不可删除');
                }
                if ($this->roleService->hasConstrait($input['id'])) {
                    $validator->errors()->add('id.roleHasConstrait', '该角色已经分配了用户，不可删除');
                }
            })->validate();
    }
}
